<?php


namespace App\Services;


use App\Models\Owner;
use App\Models\OwnerItem;
use App\Models\Send;
use App\Models\User;
use Dcat\Admin\Models\Administrator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;

/**
 * 消息推送服务
 * Class SendService
 * @package App\Services
 */
class SendService
{
    // 管理员您好，您的房产本月应收租金{1}元，已收{2}元。详情请查看：http://39.101.218.208:8090/admin/auth/login
    const TEMPLATE_662829 = 662829;

    // 管理员您好，最近30天内，有{1}个合同即将到期，请到房产租赁管理系统进行查看详情：http://39.101.218.208:8090/admin/auth/login
    const TEMPLATE_662826 = 662826;

    // 您好，{1}月租金已成功缴纳。租金为{2}，杂费为{3}元。详情查看：http://39.101.218.208:8090/
    const TEMPLATE_662819 = 662819;

    // 您好，您本月租金为{1}元，杂费为{2}元。请到管理处缴纳。详情请查看：http://39.101.218.208:8090/
    const TEMPLATE_662813 = 662813;

    // 您好管理员, 您本月的收入为{1}，更多详情请查看http://192.168.10.10/admin/auth/login
    const TEMPLATE_652773 = 652773;

    // 您好, 您本月的租金为{1}，更多详情请查看http://192.168.10.10/
    const TEMPLATE_652770 = 652770;

    public static $templateIdMapContext = [
        self::TEMPLATE_662829 => "管理员您好，您的房产本月应收租金%s元，已收%s元。详情请查看：http://39.101.218.208:8090/admin/auth/login",
        self::TEMPLATE_662826 => "管理员您好，最近30天内，有%s个合同即将到期，请到房产租赁管理系统进行查看详情：http://39.101.218.208:8090/admin/auth/login",
        self::TEMPLATE_662819 => "您好，%s月租金已成功缴纳。租金为%s，杂费为%s元。详情查看：http://39.101.218.208:8090/",
        self::TEMPLATE_662813 => "您好，您本月租金为%s元，杂费为%s元。请到管理处缴纳。详情请查看：http://39.101.218.208:8090/",
        self::TEMPLATE_652773 => "管理员您好，您的房产本月应收租金%s元，已收%s元。详情请查看：http://39.101.218.208:8090/admin/auth/login",
        self::TEMPLATE_652770 => "您好, 您本月的租金为%s，更多详情请查看http://192.168.10.10/",
    ];

    // 容器注入OwnerItemService对象
    protected $ownerItemService;
    // 注入Send模型对象
    protected $sendModel;

    public function __construct(OwnerItemService $ownerItemService, Send $send)
    {
        $this->ownerItemService = $ownerItemService;
        $this->sendModel = $send;
    }

    /**
     * 可以群发管理员的模板 id
     * @return int[]
     */
    public function canSendGroupAdmin() {
        return [
            self::TEMPLATE_662829,
            self::TEMPLATE_662826,
            self::TEMPLATE_652773
        ];
    }

    /**
     * 可以群发的合同（租客）的模板 id
     * @return int[]
     */
    public function canSendGroupOwner()
    {
        return [
            self::TEMPLATE_662819,
            self::TEMPLATE_662813,
            self::TEMPLATE_652770
        ];
    }

    /**
     * 发送短信给管理员或者承租人
     * @deprecated
     * @param $phoneNumbers static 电话号码
     * @param $code string 验证码
     * @return bool true为发送成功
     */
    public function qcloud($phoneNumbers, $money, $ownerOrAdmin = "owner")
    {
        $ownerOrAdmin = $ownerOrAdmin === "owner" ? 652770 : 652773;
        $sms  =  app('easySms');
        try {
            $sms->send($phoneNumbers, [
                'template' => $ownerOrAdmin,   // 你在腾讯云配置的"短信正文”的模板ID
                'data' => [   // data数组的内容对应于腾讯云“短信正文“里的变量
                    $money,   // 变量1
                ],
            ]);
        } catch (NoGatewayAvailableException $exception) {
            $data = $exception->getException('qcloud')->getMessage();
        }
    }

    /**
     * 不推荐使用 TEMPLATE_662829， TEMPLATE_662826 这两个模板
     * @param $phoneNumbers
     * @param $money
     * @param int $template SendService的常量
     */
    public function qcloudByTemplate($phoneNumbers, $template, $personModel, $ownerItem = null)
    {
        $sms = app('easySms');

        try {
            $sms->send($phoneNumbers, [
                'template' => $template,   // 你在腾讯云配置的"短信正文”的模板ID
                'data' => $this->getParamsByTemplateId($template, $ownerItem)
            ]);

            if (get_class($personModel) == Owner::class) {
                Send::query()->create([
                    "title" => "发送信息给{$personModel->user->name}",
                    "content" => $this->getContextByTemplateId($template, $ownerItem),
                    "type" => Send::TYPE_SMS,
                    "send_to_id" => $personModel->user_id,
                    "send_to_able" => User::class,
                    "admin_id" => Auth::guard("admin")->id(),
                ]);
            }

            if (get_class($personModel) == Administrator::class) {
                Send::query()->create([
                    "title" => "发送信息给{$personModel->username}",
                    "content" => $this->getContextByTemplateId($template),
                    "type" => Send::TYPE_SMS,
                    "send_to_id" => $personModel->id,
                    "send_to_able" => Administrator::class,
                    "admin_id" => Auth::guard("admin")->id(),
                ]);
            }

        } catch (NoGatewayAvailableException $exception) {
            $exception_msg = $exception->getException('qcloud')->getMessage();  // 腾讯短信服务的错误信息

            if (get_class($personModel) == Owner::class) {
                Send::query()->create([
                    "title" => "发送信息给{$personModel->user->name}",
                    "content" => $this->getContextByTemplateId($template, $ownerItem),
                    "type" => Send::TYPE_SMS,
                    "send_to_id" => $personModel->user_id,
                    "send_to_able" => User::class,
                    "admin_id" => Auth::guard("admin")->id(),
                    "has_exception" => true,
                    "exception_msg" => $exception_msg
                ]);
            }

            if (get_class($personModel) == Administrator::class) {
                Send::query()->create([
                    "title" => "发送信息给{$personModel->username}",
                    "content" => $this->getContextByTemplateId($template),
                    "type" => Send::TYPE_SMS,
                    "send_to_id" => $personModel->id,
                    "send_to_able" => Administrator::class,
                    "admin_id" => Auth::guard("admin")->id(),
                    "has_exception" => true,
                    "exception_msg" => $exception_msg
                ]);
            }

            return false;
        }

        return true;
    }

    /**
     * 获取某月有多少天
     * @param $date  yyyy-MM-dd
     * @return false|string
     */
    public function getMonthDays($date)
    {
        return date("t", strtotime($date));
    }

    /**
     * 获取某年有多少天
     * @param $date  yyyy-MM-dd
     * @return false|string
     */
    public function getYearDays($date)
    {
        return date("L", strtotime($date)) === 1 ? 366 : 365;
    }

    /**
     * 默认短信配置
     * @return array
     */
    private function _defaultSmsConfig()
    {
        return [
            'system_auto_send_sms_to_admin_open' => true,   // 系统自动发送给管理， true开启自动发送， false关闭
            'system_auto_send_sms_to_user_open' => true,    // 系统自动发送给用户， true开启自动发送， false关闭
            'user_send_sms_after_meter_reading' => true,  //抄表后发送短信给用户
            'send_sms_to_the_user_after_confirming_the_payment' => true,  //抄表后发送短信给用户
            'admin_send_times' => [],   // 管理员自动发送时间
            'user_send_times' => [],   // 管理员自动发送时间
            'unit' => 'month',          // 发送周期  month, year
        ];
    }

    /**
     * sms默认配置， 配置都直接保存到redis中，如果redis中没有，直接使用默认配置，同时把默认配置保存到redis中
     * （使用了redis的持久化，后面的开发者可把改为存到数据库中）
     * @param array|string $userSendTimes
     * @param array|string $adminSendTimes
     * @param string $unit
     * @param bool $autoSendSmsToAdminOpen
     * @param bool $autoSendSmsToUser
     * @param bool $sendSmsAfterMeterReading
     * @param bool $sendSmsAfterPayment
     * @return bool
     */
    public function setSmsConfig(
        $userSendTimes,
        $adminSendTimes,
        $unit = 'month',
        $autoSendSmsToAdminOpen = true,
        $autoSendSmsToUser = true,
        $sendSmsAfterMeterReading = true,
        $sendSmsAfterPayment = true
    ) {
        if (!is_array($userSendTimes)) {
            $userSendTimes = [$userSendTimes];
        }
        if (!is_array($adminSendTimes)) {
            $adminSendTimes = [$adminSendTimes];
        }

        // $userSendTimes | $adminSendTimes 和 $unit是否匹配

        return Cache::forever(
            'sms_config',
            [
                'system_auto_send_sms_to_admin_open' => $autoSendSmsToAdminOpen,
                'system_auto_send_sms_to_user_open' => $autoSendSmsToUser,
                'user_send_sms_after_meter_reading' => $sendSmsAfterMeterReading,
                'send_sms_to_the_user_after_confirming_the_payment' => $sendSmsAfterPayment,
                'admin_send_times' => $adminSendTimes,
                'user_send_times' => $userSendTimes,
                'unit' => $unit,
            ]
        );
    }

    /**
     * 获取缓存中的短信配置
     * @return mixed
     */
    public function getSmsConfig()
    {
        return Cache::get('sms_config');
    }

    /**
     * 根据不同的模板id获取不同的参数
     * 注意：使用 662819 和 662813模板时必须注入OwnerItem(而且是已经抄表的OwnerItem对象)。 其他模板不用传入
     * @param $templateId
     * @param OwnerItem|null $ownerItem
     * @return array
     */
    public function getParamsByTemplateId($templateId, OwnerItem $ownerItem = null)
    {
        switch ($templateId) {
            case 662829:
                $arr = $this->template_params_662829();
                break;
            case 662826:
                $arr = $this->template_params_662826();
                break;
            case 662819:
                if ($ownerItem == null) throw new \Exception("请注入OwnerItem对象");
                $arr = $this->template_params_662819($ownerItem);
                break;
            case 662813:
                if ($ownerItem == null) throw new \Exception("请注入OwnerItem对象");
                $arr = $this->template_params_662813($ownerItem);
                break;
            case 652773:
                $arr = $this->template_params_652773();
                break;
            case 652770:
                $arr = $this->template_params_652770();
                break;
            default:
                break;
        }
        return $arr;
    }


    /**
     * 根据不同的模板id获取不同的内容
     * 注意：使用 662819 和 662813模板时必须注入OwnerItem(而且是已经抄表的OwnerItem对象)。 其他模板不用传入
     * @param $templateId
     * @param OwnerItem|null $ownerItem
     */
    public function getContextByTemplateId($templateId, OwnerItem $ownerItem = null)
    {
        $content = "";
        switch ($templateId) {
            case 662829:
                $content = $this->template_662829();
                break;
            case 662826:
                $content = $this->template_662826();
                break;
            case 662819:
                if ($ownerItem == null) throw new \Exception("请注入OwnerItem对象");
                $content = $this->template_662819($ownerItem);
                break;
            case 662813:
                if ($ownerItem == null) throw new \Exception("请注入OwnerItem对象");
                $content = $this->template_662813($ownerItem);
                break;
            case 652773:
                $content = $this->template_652773();
                break;
            case 652770:
                $content = $this->template_652770();
                break;
            default:
                break;
        }
        return $content;
    }

    // 管理员您好，您的房产本月应收租金{1}元，已收{2}元。详情请查看：http://39.101.218.208:8090/admin/auth/login
    public function template_662829()
    {
        $content = self::$templateIdMapContext[self::TEMPLATE_662829];  // 文字内容
        $rent = $this->ownerItemService->getRentThisMonth();  // 本月应收
        $alreadyRent = $this->ownerItemService->getRentAlreadyIncomeThisMonth();   // 本月实收
        return sprintf($content, $rent, $alreadyRent);
    }

    // 管理员您好，最近30天内，有{1}个合同即将到期，请到房产租赁管理系统进行查看详情：http://39.101.218.208:8090/admin/auth/login
    public function template_662826()
    {
        $content = self::$templateIdMapContext[self::TEMPLATE_662826];
        $count = $this->ownerItemService->getLast30DaysExpiredContractsCount();
        return sprintf($content, $count);
    }

    // 您好，{1}月租金已成功缴纳。租金为{2}，杂费为{3}元。详情查看：http://39.101.218.208:8090/
    public function template_662819(OwnerItem $ownerItem)
    {
        $content = self::$templateIdMapContext[self::TEMPLATE_662819];
        $month = $this->ownerItemService->getOwnerItemMonth($ownerItem);
        $rent = $this->ownerItemService->getOwnerItemRent($ownerItem);
        $otherAndOnceAmount = $this->ownerItemService->getOwnerItemOtherOnce($ownerItem);
        return sprintf($content, $month, $rent, $otherAndOnceAmount);
    }

    // 您好，您本月租金为{1}元，杂费为{2}元。请到管理处缴纳。详情请查看：http://39.101.218.208:8090/
    public function template_662813(OwnerItem $ownerItem)
    {
        $content = self::$templateIdMapContext[self::TEMPLATE_662813];
        $rent = $this->ownerItemService->getOwnerItemRent($ownerItem);
        $otherAndOnceAmount = $this->ownerItemService->getOwnerItemOtherOnce($ownerItem);
        return sprintf($content, $rent, $otherAndOnceAmount);
    }

    // 管理员您好，您的房产本月应收租金{1}元，已收{2}元。详情请查看：http://39.101.218.208:8090/admin/auth/login
    public function template_652773()
    {
        $content = self::$templateIdMapContext[self::TEMPLATE_652773];
        $rent = $this->ownerItemService->getRentThisMonth();  // 本月应收
        $alreadyRent = $this->ownerItemService->getRentAlreadyIncomeThisMonth();   // 本月实收
        return sprintf($content, $rent, $alreadyRent);
    }

    // 您好, 您本月的租金为{1}，更多详情请查看http://192.168.10.10/
    public function template_652770()
    {
        $content = self::$templateIdMapContext[self::TEMPLATE_652770];
        $rent = $this->ownerItemService->getRentThisMonth();  // 本月应收
        return sprintf($content, $rent);
    }


    // 管理员您好，您的房产本月应收租金{1}元，已收{2}元。详情请查看：http://39.101.218.208:8090/admin/auth/login
    public function template_params_662829()
    {
        $rent = $this->ownerItemService->getRentThisMonth();  // 本月应收
        $alreadyRent = $this->ownerItemService->getRentAlreadyIncomeThisMonth();   // 本月实收
        return [$rent, $alreadyRent];
    }

    // 管理员您好，最近30天内，有{1}个合同即将到期，请到房产租赁管理系统进行查看详情：http://39.101.218.208:8090/admin/auth/login
    public function template_params_662826()
    {
        $count = $this->ownerItemService->getLast30DaysExpiredContractsCount();
        return [$count];
    }

    // 您好，{1}月租金已成功缴纳。租金为{2}，杂费为{3}元。详情查看：http://39.101.218.208:8090/
    public function template_params_662819(OwnerItem $ownerItem)
    {
        $month = $this->ownerItemService->getOwnerItemMonth($ownerItem);
        $rent = $this->ownerItemService->getOwnerItemRent($ownerItem);
        $otherAndOnceAmount = $this->ownerItemService->getOwnerItemOtherOnce($ownerItem);
        return [$month, $rent, $otherAndOnceAmount];
    }

    // 您好，您本月租金为{1}元，杂费为{2}元。请到管理处缴纳。详情请查看：http://39.101.218.208:8090/
    public function template_params_662813(OwnerItem $ownerItem)
    {
        $rent = $this->ownerItemService->getOwnerItemRent($ownerItem);
        $otherAndOnceAmount = $this->ownerItemService->getOwnerItemOtherOnce($ownerItem);
        return [$rent, $otherAndOnceAmount];
    }

    // 管理员您好，您的房产本月应收租金{1}元，已收{2}元。详情请查看：http://39.101.218.208:8090/admin/auth/login
    public function template_params_652773()
    {
        $rent = $this->ownerItemService->getRentThisMonth();  // 本月应收
        $alreadyRent = $this->ownerItemService->getRentAlreadyIncomeThisMonth();   // 本月实收
        return [$rent, $alreadyRent];
    }

    // 您好, 您本月的租金为{1}，更多详情请查看http://192.168.10.10/
    public function template_params_652770()
    {
        $rent = $this->ownerItemService->getRentThisMonth();  // 本月应收
        return [$rent];
    }
}